package com.itheima.day14.threadStatus.test1;

//目的 : 本案例主要演示BLOCKED的状态转换。
//        需求 ：编写一段代码，依次显示一个线程的这些状态：NEW -> RUNNABLE -> BLOCKED -> RUNNABLE ->
//        TERMINATED
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        // 定义一个对象，用来加锁和解锁
        Object obj = new Object();

        // 定义一个线程，先抢占了obj对象的锁
        new Thread(()->{
            synchronized (obj){
                try {
                    // 第一个线程要只有锁100毫秒
                    Thread.sleep(100);

                    // 然后通过wait()方法进行等待状态，并释放obj的对象锁
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        // 定义目标线程，获取等待获取obj的锁
        Thread t = new Thread(()->{
            System.out.println("2.执行t.start()之后，线程的状态：" + Thread.currentThread().getState());
            synchronized (obj){
                try {
                    // t要坚持对象线索100毫秒
                    Thread.sleep(100);

                    // 然后通过notify()方法唤醒所有在obj上等待的线程继续执行后续操作
                    obj.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("4.阻塞结束后，线程的状态：" + Thread.currentThread().getState());
        });

        // 获取start()之前的状态
        System.out.println("1.通过new初始化一个线程，但是还没有start()之前，线程的状态：" + t.getState());

        // 启动线程
        t.start();

        // 先等50毫秒
        Thread.sleep(50);

        // 第一个线程释放锁至少需要100毫秒，所以在第50毫秒时，t正因为等待obj的对象锁而阻塞
        System.out.println("3.因为等待锁而阻塞时，线程的状态：" + t.getState());

        // 在等300毫秒
        Thread.sleep(300);

        // 两个线程的执行时间加上等待的50毫秒总过时250毫秒，所以第300毫秒，所有线程都已经执行完毕
        System.out.println("5.线程执行完毕之后，线程的状态：" + t.getState());
    }
    // 打印结果：
//      1.通过new初始化一个线程，但是还没有start()之前，线程的状态：NEW
//      2.执行t.start()之后，线程的状态：RUNNABLE
//      3.因为等待锁而阻塞时，线程的状态：BLOCKED
//      4.阻塞结束后，线程的状态：RUNNABLE
//      5.线程执行完毕之后，线程的状态：TERMINATED
}
